library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--use ieee.numeric_std.all;
use work.dec_pkg.all;
entity op_control is port (
	rst : in std_ulogic;
	clk : in std_ulogic;
	request : in std_ulogic;
        cup_outflag : in std_ulogic; 
	cup_enable2: out std_ulogic;
	vup_enable2 : out std_ulogic;
	cup1_beginning : out std_ulogic;
	cup16_end2: out std_ulogic;
        read :out std_ulogic;
	--r_en : out std_ulogic_vector(7 downto 0);
	write :out std_ulogic;
	--w_en :out std_ulogic_vector(7 downto 0);
       state12  :out  std_ulogic;
	ack : out std_ulogic;
        ppin_flag : in std_ulogic;
	ppout_flag: in std_ulogic;
	op_end :out std_ulogic;
	addr : out std_ulogic_vector(8 downto 0);
	count_cr2 : out std_ulogic_vector(7 downto 0);
	count_cw2 : out std_ulogic_vector(7 downto 0);
  count_vr2 : out std_ulogic_vector(6 downto 0);
	count_vw2 : out std_ulogic_vector(6 downto 0);
	count_jw2 : out std_ulogic_vector(6 downto 0);
	wenr1 : out  std_ulogic_vector(7 downto 0);
	wenr2 : out  std_ulogic_vector(7 downto 0);
	wenr3 : out  std_ulogic_vector(7 downto 0);
	wenr4 : out  std_ulogic_vector(7 downto 0);
	wenr5 : out  std_ulogic_vector(7 downto 0);
	wenr6 : out  std_ulogic_vector(7 downto 0);
	wenr7 : out  std_ulogic_vector(7 downto 0);
	wenr8 : out  std_ulogic_vector(7 downto 0);
	bl :out  integer range 50 to 512;
  enablex : out std_ulogic_vector(7 downto 0);
	wb_clk : in std_ulogic;
	wb_en : in std_ulogic;
	wb_addr : in std_ulogic_vector(15 downto 0);
  wb_data : in std_ulogic_vector(15 downto 0);
	wb_en2 : out std_ulogic;
	wb_addr2 : out std_ulogic_vector(15 downto 0);
  wb_data2 : out std_ulogic_vector(15 downto 0)
	);
end entity ;
architecture rtl of op_control is
	type states is (idle ,cup_state , cup_out_state, vup_state , vup_out_state , judge_state,judge_out_state);--  all kinds of  states
        signal dec_state : states;-- denote the current states
	signal jcnt ,vcnt : std_logic_vector(2 downto 0);
	signal cup_finish_flag,vup_finish_flag,judge_finish_flag : std_ulogic;
	signal iteration_count : std_ulogic_vector(4 downto 0);
        signal x,y :std_ulogic;
	signal state1 : std_ulogic;
	signal cup_enable ,vup_enable :std_ulogic;
	signal ack1 : std_ulogic;
	signal count_cr,count_cw : std_ulogic_vector(7 downto 0);
        signal count_vr,count_vw,count_temp ,judge_count_temp,count_jw: std_ulogic_vector(6 downto 0);
        signal  vup_outflag,judge_outflag :std_ulogic;
        signal b_len	: block_length ;					--default:  block length 50;
        signal f_len	: frame_length ;					--default:  frame length 400;
        signal vup_length :frame_length ; --default :vup rate adaption 400;
        signal half_blen : integer ; 
	signal cup16_end : std_ulogic;
	signal wen : std_ulogic_vector(127 downto 0) ;
	--signal wb_clk1 :  std_ulogic;
  signal wb_en1 :  std_ulogic;
  signal wb_addr1 :  std_ulogic_vector(15 downto 0);
  signal wb_data1 :  std_ulogic_vector(15 downto 0);
begin 
  wb_data2 <= wb_data1;
  wb_addr2 <= wb_addr1;
  wb_en2 <= wb_en1;
  process(wb_clk)
    begin 
      if wb_clk'event and wb_clk = '1' then 
         wb_en1 <= wb_en ;
         wb_addr1 <= wb_addr;
         wb_data1 <= wb_data;
       end if ;
     end  process ;
  count_cr2 <= count_cr ;
	count_cw2 <= count_cw;
	count_vr2 <= count_vr;
	count_vw2 <= count_vw;
	count_jw2 <= count_jw;
	bl <= b_len ;
	state12 <= state1;
         wenr1 <=   wen(7) & wen(6) & wen(5) & wen(4) & wen(3) & wen(2) & wen(1) & wen(0);
         wenr2 <=   wen(15) & wen(14) & wen(13) & wen(12) & wen(11) & wen(10) & wen(9) & wen(8);
         wenr3 <=   wen(23) & wen(22) & wen(21) & wen(20) & wen(19) & wen(18) & wen(17) & wen(16);
         wenr4 <=   wen(31) & wen(30) & wen(29) & wen(28) & wen(27) & wen(26) & wen(25) & wen(24);
         wenr5 <=   wen(39) & wen(38) & wen(37) & wen(36) & wen(35) & wen(34) & wen(33) & wen(32);
         wenr6 <=   wen(47) & wen(46) & wen(45) & wen(44) & wen(43) & wen(42) & wen(41) & wen(40);
         wenr7 <=   wen(55) & wen(54) & wen(53) & wen(52) & wen(51) & wen(50) & wen(49) & wen(48);
         wenr8 <=   wen(63) & wen(62) & wen(61) & wen(60) & wen(59) & wen(58) & wen(57) & wen(56);
   process (cup_enable,x,y,judge_outflag,ppin_flag,ppout_flag,count_cr,count_jw)
   begin 
    if cup_enable = '1' then 
        addr <= x & count_cr;
    elsif judge_outflag = '1' then 
       addr <= y & count_jw & '0';
     else 
       addr <= (others => '0');
     end if ;
   end process;
op_end <= judge_finish_flag and cup16_end ;
read <= cup_enable ;
write <= judge_outflag;

cup16_end2 <= cup16_end; 
process (wb_addr1,wb_en1)
  variable x:integer ;
  begin 
    if wb_en1 = '1' then 
    if wb_addr1(15) = '1'  then 
       wen <= (others => '0'); 
    else 
       x := to_int(wb_addr1(14 downto 8));
       wen <= gen(x);
     end  if;
   else 
     wen <= (others => '0');
   end if;
     end process;
process (wb_clk,wb_en1)
  begin 
    if wb_en1 = '1' then 
    if wb_clk'event and wb_clk = '1' then 
    if wb_addr1(15 downto 0) = "1000000000000000" then 
          b_len <= to_int(wb_data1(15 downto 0));
    elsif wb_addr1(15 downto 0) = "1000000000000001" then 
          f_len <= to_int(wb_data1(15 downto 0));
    elsif wb_addr1(15 downto 0) = "1000000000000011" then 
          half_blen <= to_int(wb_data1(15 downto 0));
    end if;
  end if ;
    end if;
end process;

process (clk)
  begin 
    if clk'event and clk = '1' then
    if state1 = '0' then 
       x <= ppin_flag ;
       y <= ppout_flag ;
       end if;
       end if;
       end process;


       dec_st : process (clk ,rst)
       begin
       if rst = '0' then dec_state <= idle;
        elsif clk'event and clk = '1' then 
       case dec_state is 

       when idle => if request = '1'  then 
		                 dec_state <= cup_state;  -- the idle  state 
		  else 
				 dec_state <= dec_state ;
		 end if;
		when cup_state => if cup_outflag = '1' then dec_state <= cup_out_state;  -- cup_state  cup is running 
		                  else dec_state <= dec_state ;
				 end if;
		when cup_out_state => if cup_finish_flag = '1' then                       --cup_output_state  
		                          if iteration_count = "01111" then               -- if the iteration counter is 16 then enter into the judge module else vup module 
					 dec_state <= judge_state;
				        	else 
					 dec_state <= vup_state;
					end if;
	                         else 
	                                 dec_state <= dec_state;
			                   end if;
	 	when vup_state => if vup_outflag = '1' then dec_state <= vup_out_state ;      -- vup_state vup is running 
                        else dec_state <= dec_state;
						      end if;
		when vup_out_state => if vup_finish_flag = '1' then                        
                               dec_state <= cup_state ;
									else dec_state <= dec_state ;
							      end if ;
		when judge_state => if judge_outflag = '1' then 
		                       dec_state <= judge_out_state;									 
									else dec_state <= dec_state ;
									    
									end if;
		when judge_out_state => if judge_finish_flag = '1' then 
		                        dec_state <= idle;
										else dec_state <= dec_state ;
										 end if;
	end case;
end if ;
end process;



cup_enable2 <= cup_enable ;
vup_enable2 <= vup_enable;

process (clk)
begin 
	if clk'event and clk = '1' then 
		ack <= ack1;
	end if;
end process;

dec_control:process (dec_state ,iteration_count,request)
begin
case dec_state is 
      when idle =>  cup_enable <= '0' ;
		    vup_enable <= '0';
		    cup1_beginning  <= '0' ;
		    cup16_end  <= '0' ;
		    state1 <= '0';
		    ack1 <= '1' and request;
						
      when cup_state => if iteration_count = "00000" then 
		                       cup_enable <= '1' ;
		                       vup_enable <= '0' ;
				       cup1_beginning  <= '1' ;
				       cup16_end  <= '0' ;	
				       ack1 <= '0';
         			       state1 <= '1';
								
									  
								else
							       cup_enable <= '1' ;
									 vup_enable <= '0' ;
									 cup1_beginning<= '0' ;
									 cup16_end  <= '0' ;
									 ack1 <= '0';
									  state1 <= '1';
								
								end if;
		 when cup_out_state => if iteration_count = "00000" then 
		                          cup_enable <= '1' ;
		                          vup_enable <= '0'; 
									            ack1 <= '0';
									            cup1_beginning<= '1' ;
									            cup16_end  <= '0' ;
									             state1 <= '1';
									         
									       else 
									            cup_enable <= '1' ;
									            vup_enable <= '0' ;
									            cup1_beginning<= '0' ;
									            cup16_end  <= '0' ;
									            ack1 <= '0';
									             state1 <= '1';
									          
									         end if;
		when vup_state => vup_enable <= '1';
		                  cup_enable <= '0';
								      ack1 <= '0';
								      cup1_beginning<= '0' ;
									    cup16_end  <= '0' ;
									     state1 <= '1';
									
		when  vup_out_state => vup_enable <= '1' ;
	                         cup_enable <= '0' ;
									         ack1 <= '0';
									         cup1_beginning<= '0' ;
									          state1 <= '1';
									         cup16_end  <= '0' ;
									   
		when  judge_state =>   cup_enable <= '0';
                           vup_enable <= '1' ;
							             cup16_end  <= '1' ;
									         cup1_beginning<= '0' ;
									         ack1 <= '0';
									         state1 <= '1';
									    
		when judge_out_state => cup_enable <= '0';
                            vup_enable <= '1' ;
							              cup16_end  <= '1' ;
									          ack1 <= '0';
									          cup1_beginning<= '0' ;
									          state1 <= '1';
									     

	end case ;	
end process;	


process(cup_finish_flag,clk,rst)
begin 
  if rst = '0' then 
    iteration_count <= "00000";
  elsif clk'event and clk = '1' then 
    if  cup_finish_flag = '1' then 
	      if iteration_count = "01111"
			then
		        iteration_count <= "00000";
				 else 
				  iteration_count <=  CONV_STD_ULOGIC_VECTOR(to_int(iteration_count) + 1,5);
				 end if ;
				else 
			    iteration_count <= iteration_count ;
				end if;
				end if;
			end process;	
								
-----------------------------------------------------------------------------
-------------------------------cup read address generator -------------------								
process (clk,rst)
   begin 
     if rst = '0' then
         count_cr <= (others => '0'); 
	 elsif clk'event and clk = '1' then 
	     if cup_enable = '1' then 
	     if to_stdlogicvector(count_cr) = b_len - 1  then 
			 count_cr <= count_cr;
		  else  
		     count_cr <= to_stdulogicvector((to_stdlogicvector(count_cr) + 1 ));
			
		 end if;
	  else 
	        count_cr <= (others => '0') ;		
		end if;
	end if ;
end process;              
	
	
---------------------------------------------------------------------------
----------------------------cup write address generator -------------------
---------------------------and if count cw = 50 then cup finish -----------
---------------------------------------------------------------------------	
process (clk,rst,cup_enable)
   begin 
   if rst = '0' then 
        cup_finish_flag <= '0';
        count_cw <= (others =>'0'); 
  elsif cup_enable = '0' then 
         cup_finish_flag <= '0' ;
  elsif clk'event and clk = '1' then 
	  if cup_outflag = '1'  then 
			 if to_stdlogicvector(count_cw) = b_len - 1 then 
					 cup_finish_flag <= '1';
		  else
		          cup_finish_flag <= '0';
		          count_cw <= CONV_STD_ULOGIC_VECTOR(to_int(count_cw) + 1,8);
		 end if;
	 else 
	             cup_finish_flag <= '0';
	             count_cw <= (others => '0') ;
		 end if;
		end if;
end process;	
--------------------------------------------------------------------------
-----------------------vup memory read control --------------------------- 							   
process (clk,rst)
   begin 
     if rst = '0' then 
       count_vr <= (others => '0');
    elsif clk'event and clk = '1' then 
	   if vup_enable = '1' then 
	     if to_stdlogicvector(count_vr) = half_blen - 1 then 
		      count_vr <= (others => '0') ;
		  elsif to_stdlogicvector(count_vr) < half_blen - 1 then 
		   count_vr <= CONV_STD_ULOGIC_VECTOR(to_int(count_vr) + 1,7);
			 else 
			  count_vr <= count_vr;
		end if;
	     else 
	         count_vr <= (others => '0');
		end if;
	end if ;
end process;

----------------------------------------------------------------------------------------
------------ vup memory write control--------------------------------------------------
------------vnt_cw is the address to  access the address of the write address of memory bank--
process (clk,rst)
   begin 
     if rst = '0' then 
        vup_finish_flag <= '0';
        count_vw <= (others => '0');
        count_temp <= (others=> '0');
    elsif clk'event and clk = '1' then 
	   if vup_outflag = '1'  then 
	      if to_stdlogicvector(count_temp) = half_blen - 2 then 
			    vup_finish_flag <= '1';
			   else 
			      count_temp <= CONV_STD_ULOGIC_VECTOR(to_int(count_temp) + 1,7);
			      vup_finish_flag <= '0';
			    end if;
		     if to_stdlogicvector(count_vw) = half_blen - 1 then 
		            count_vw <= (others => '0');
		     else  
		       count_vw <= CONV_STD_ULOGIC_VECTOR(to_int(count_vw) + 1,7);
		    	end if; 
	  else 
	        vup_finish_flag <= '0';
	        count_vw <= (others => '0');	 
	        count_temp <= (others=> '0');
		end if;
	end if ;
end process;
--------------------------------------------------------------------------------------------
---------------------------------judge output control -------------------------------
------------------------------when count_jw = 50 then judge jump ----------------------
process (clk,rst)
   begin 
   if  rst = '0' then 
       judge_finish_flag <= '0';
       count_jw <= (others => '0');
       judge_count_temp <= (others => '0');  	
	elsif clk'event and clk = '1' then 
	  if  judge_outflag = '1' then 
	     if to_stdlogicvector(judge_count_temp) = half_blen - 3  then
	     judge_finish_flag <= '1' ;
	     else 
	        judge_count_temp <= conv_std_ulogic_vector(to_int(judge_count_temp) + 1,7) ;
	        judge_finish_flag <= '0';
	     end if;
			 if to_stdlogicvector(count_jw) = half_blen - 1 then 
			       count_jw <= (others => '0');
		  else
		         
		          count_jw <= CONV_STD_ULOGIC_VECTOR(to_int(count_jw) + 1,7);
		 end if;
	 else 
	             judge_finish_flag <= '0';
	             count_jw <= (others => '0') ;
	             judge_count_temp <= (others => '0');
		 end if;
		end if;
end process;		


process(clk,rst)
begin
  if rst = '0'then 
     vcnt <= (others =>'0');
     vup_outflag <= '0';
  elsif clk'event and clk='1' then
  if vup_enable='1' then   
       if vcnt="011" then
           vup_outflag<='1';    
       else 
         vcnt <= vcnt + 1;
         vup_outflag<='0';
       end if;
    else
      vcnt <= "000";
      vup_outflag<='0';
    end if;
  end if;
end process;
---------------judge outflag gen ---------------------
process(clk,rst) 
begin
  if rst = '0'then 
     jcnt <= (others =>'0');
     judge_outflag <= '0';
  elsif clk'event and clk='1' then
  if cup16_end ='1' then   
       if jcnt="010" then
           judge_outflag<='1';    
       else 
         jcnt<=jcnt+1;
        judge_outflag<='0';
       end if;
    else
      jcnt <= "000";
      judge_outflag<='0';
    end if;
  end if;
end process;

enablex(0) <= (not wb_addr1(10)) and (not wb_addr1(9)) and (not wb_addr1(8));
enablex(1) <= (not wb_addr1(10)) and (not wb_addr1(9)) and ( wb_addr1(8));
enablex(2) <= (not wb_addr1(10)) and  wb_addr1(9) and (not wb_addr1(8));
enablex(3) <= (not wb_addr1(10)) and ( wb_addr1(9)) and ( wb_addr1(8));
enablex(4) <= ( wb_addr1(10)) and (not wb_addr1(9)) and (not wb_addr1(8));
enablex(5) <= ( wb_addr1(10)) and (not wb_addr1(9)) and ( wb_addr1(8));
enablex(6) <= ( wb_addr1(10)) and ( wb_addr1(9)) and (not wb_addr1(8));
enablex(7) <= ( wb_addr1(10)) and ( wb_addr1(9)) and (wb_addr1(8));
end rtl;
